<?php
/**
 * 文章内允许出现的html标签和属性
 * @return array
 */
function wp_get_allowedposttags()
{
    $allowedposttags = array(
        'address' => array(),
        'a' => array(
            'class' => array(),
            'href' => array(),
            'id' => array(),
            'title' => array(),
            'rel' => array(),
            'rev' => array(),
            'name' => array(),
            'target' => array()),
        'abbr' => array(
            'class' => array(),
            'title' => array()),
        'acronym' => array(
            'title' => array()),
        'b' => array(),
        'big' => array(),
        'blockquote' => array(
            'id' => array(),
            'cite' => array(),
            'class' => array(),
            'lang' => array(),
            'xml:lang' => array()),
        'br' => array(
            'class' => array()),
        'button' => array(
            'disabled' => array(),
            'name' => array(),
            'type' => array(),
            'value' => array()),
        'caption' => array(
            'align' => array(),
            'class' => array()),
        'cite' => array(
            'class' => array(),
            'dir' => array(),
            'lang' => array(),
            'title' => array()),
        'code' => array(
            'style' => array()),
        'col' => array(
            'align' => array(),
            'char' => array(),
            'charoff' => array(),
            'span' => array(),
            'dir' => array(),
            'style' => array(),
            'valign' => array(),
            'width' => array()),
        'del' => array(
            'datetime' => array()),
        'dd' => array(),
        'div' => array(
            'align' => array(),
            'class' => array(),
            'dir' => array(),
            'lang' => array(),
            'style' => array(),
            'xml:lang' => array()),
        'dl' => array(),
        'dt' => array(),
        'em' => array(),
        'fieldset' => array(),
        'font' => array(
            'color' => array(),
            'face' => array(),
            'size' => array()),
        'form' => array(
            'action' => array(),
            'accept' => array(),
            'accept-charset' => array(),
            'enctype' => array(),
            'method' => array(),
            'name' => array(),
            'target' => array()),
        'h1' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'h2' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'h3' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'h4' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'h5' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'h6' => array(
            'align' => array(),
            'class' => array(),
            'id' => array(),
            'style' => array()),
        'hr' => array(
            'align' => array(),
            'class' => array(),
            'noshade' => array(),
            'size' => array(),
            'width' => array()),
        'i' => array(),
        'img' => array(
            'alt' => array(),
            'align' => array(),
            'border' => array(),
            'class' => array(),
            'height' => array(),
            'hspace' => array(),
            'longdesc' => array(),
            'vspace' => array(),
            'src' => array(),
            'style' => array(),
            'width' => array()),
        'ins' => array(
            'datetime' => array(),
            'cite' => array()),
        'kbd' => array(),
        'label' => array(
            'for' => array()),
        'legend' => array(
            'align' => array()),
        'li' => array(
            'align' => array(),
            'class' => array()),
        'p' => array(
            'class' => array(),
            'align' => array(),
            'dir' => array(),
            'lang' => array(),
            'style' => array(),
            'xml:lang' => array()),
        'pre' => array(
            'style' => array(),
            'class' => array(),
            'data-language' => array(),
            'width' => array()),
        'q' => array(
            'cite' => array()),
        's' => array(),
        'span' => array(
            'class' => array(),
            'dir' => array(),
            'align' => array(),
            'lang' => array(),
            'style' => array(),
            'title' => array(),
            'xml:lang' => array()),
        'strike' => array(),
        'strong' => array(),
        'sub' => array(),
        'sup' => array(),
        'table' => array(
            'align' => array(),
            'bgcolor' => array(),
            'border' => array(),
            'cellpadding' => array(),
            'cellspacing' => array(),
            'class' => array(),
            'dir' => array(),
            'id' => array(),
            'rules' => array(),
            'style' => array(),
            'summary' => array(),
            'width' => array()),
        'tbody' => array(
            'align' => array(),
            'char' => array(),
            'charoff' => array(),
            'valign' => array()),
        'td' => array(
            'abbr' => array(),
            'align' => array(),
            'axis' => array(),
            'bgcolor' => array(),
            'char' => array(),
            'charoff' => array(),
            'class' => array(),
            'colspan' => array(),
            'dir' => array(),
            'headers' => array(),
            'height' => array(),
            'nowrap' => array(),
            'rowspan' => array(),
            'scope' => array(),
            'style' => array(),
            'valign' => array(),
            'width' => array()),
        'tfoot' => array(
            'align' => array(),
            'char' => array(),
            'class' => array(),
            'charoff' => array(),
            'valign' => array()),
        'th' => array(
            'abbr' => array(),
            'align' => array(),
            'axis' => array(),
            'bgcolor' => array(),
            'char' => array(),
            'charoff' => array(),
            'class' => array(),
            'colspan' => array(),
            'headers' => array(),
            'height' => array(),
            'nowrap' => array(),
            'rowspan' => array(),
            'scope' => array(),
            'valign' => array(),
            'width' => array()),
        'thead' => array(
            'align' => array(),
            'char' => array(),
            'charoff' => array(),
            'class' => array(),
            'valign' => array()),
        'title' => array(),
        'tr' => array(
            'align' => array(),
            'bgcolor' => array(),
            'char' => array(),
            'charoff' => array(),
            'class' => array(),
            'style' => array(),
            'valign' => array()),
        'tt' => array(),
        'video' => array(
            'autoplay' => array(),
            'controls' => array(),
            'height' => array(),
            'loop' => array(),
            'preload' => array(),
            'src' => array(),
            'width' => array()),
        'audio' => array(
            'autoplay' => array(),
            'controls' => array(),
            'height' => array(),
            'loop' => array(),
            'preload' => array(),
            'src' => array(),
            'width' => array()),
        'u' => array(),
        'ul' => array(
            'class' => array(),
            'style' => array(),
            'type' => array()),
        'ol' => array(
            'class' => array(),
            'start' => array(),
            'style' => array(),
            'type' => array()),
        'var' => array());
    $allowedposttags = array_map('_wp_add_global_attributes', $allowedposttags);
    return $allowedposttags;
}

function apply_filters($filter, $data)
{
    return $data;
}

function _deprecated_argument($arg1, $arg2)
{
    return true;
}

function get_allowedtags()
{
    return array(
        'a' => array(
            'href' => true,
            'title' => true,
        ),
        'abbr' => array(
            'title' => true,
        ),
        'acronym' => array(
            'title' => true,
        ),
        'b' => array(),
        'blockquote' => array(
            'cite' => true,
        ),
        'cite' => array(),
        'code' => array(),
        'del' => array(
            'datetime' => true,
        ),
        'em' => array(),
        'i' => array(),
        'q' => array(
            'cite' => true,
        ),
        'strike' => array(),
        'strong' => array(),
    );
}


function get_allowedentitynames()
{
    return array(
        'nbsp', 'iexcl', 'cent', 'pound', 'curren', 'yen',
        'brvbar', 'sect', 'uml', 'copy', 'ordf', 'laquo',
        'not', 'shy', 'reg', 'macr', 'deg', 'plusmn',
        'acute', 'micro', 'para', 'middot', 'cedil', 'ordm',
        'raquo', 'iquest', 'Agrave', 'Aacute', 'Acirc', 'Atilde',
        'Auml', 'Aring', 'AElig', 'Ccedil', 'Egrave', 'Eacute',
        'Ecirc', 'Euml', 'Igrave', 'Iacute', 'Icirc', 'Iuml',
        'ETH', 'Ntilde', 'Ograve', 'Oacute', 'Ocirc', 'Otilde',
        'Ouml', 'times', 'Oslash', 'Ugrave', 'Uacute', 'Ucirc',
        'Uuml', 'Yacute', 'THORN', 'szlig', 'agrave', 'aacute',
        'acirc', 'atilde', 'auml', 'aring', 'aelig', 'ccedil',
        'egrave', 'eacute', 'ecirc', 'euml', 'igrave', 'iacute',
        'icirc', 'iuml', 'eth', 'ntilde', 'ograve', 'oacute',
        'ocirc', 'otilde', 'ouml', 'divide', 'oslash', 'ugrave',
        'uacute', 'ucirc', 'uuml', 'yacute', 'thorn', 'yuml',
        'quot', 'amp', 'lt', 'gt', 'apos', 'OElig',
        'oelig', 'Scaron', 'scaron', 'Yuml', 'circ', 'tilde',
        'ensp', 'emsp', 'thinsp', 'zwnj', 'zwj', 'lrm',
        'rlm', 'ndash', 'mdash', 'lsquo', 'rsquo', 'sbquo',
        'ldquo', 'rdquo', 'bdquo', 'dagger', 'Dagger', 'permil',
        'lsaquo', 'rsaquo', 'euro', 'fnof', 'Alpha', 'Beta',
        'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta',
        'Iota', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Xi',
        'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon',
        'Phi', 'Chi', 'Psi', 'Omega', 'alpha', 'beta',
        'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta',
        'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi',
        'omicron', 'pi', 'rho', 'sigmaf', 'sigma', 'tau',
        'upsilon', 'phi', 'chi', 'psi', 'omega', 'thetasym',
        'upsih', 'piv', 'bull', 'hellip', 'prime', 'Prime',
        'oline', 'frasl', 'weierp', 'image', 'real', 'trade',
        'alefsym', 'larr', 'uarr', 'rarr', 'darr', 'harr',
        'crarr', 'lArr', 'uArr', 'rArr', 'dArr', 'hArr',
        'forall', 'part', 'exist', 'empty', 'nabla', 'isin',
        'notin', 'ni', 'prod', 'sum', 'minus', 'lowast',
        'radic', 'prop', 'infin', 'ang', 'and', 'or',
        'cap', 'cup', 'int', 'sim', 'cong', 'asymp',
        'ne', 'equiv', 'le', 'ge', 'sub', 'sup',
        'nsub', 'sube', 'supe', 'oplus', 'otimes', 'perp',
        'sdot', 'lceil', 'rceil', 'lfloor', 'rfloor', 'lang',
        'rang', 'loz', 'spades', 'clubs', 'hearts', 'diams',
        'sup1', 'sup2', 'sup3', 'frac14', 'frac12', 'frac34',
        'there4',
    );
}


function kses($string, $allowed_html = array())
{
    $allowed_protocols = array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp');
    if (empty($allowed_html)) {
        $allowed_html = wp_get_allowedposttags();
    }
    $string = wp_kses_no_null($string);
    $string = wp_kses_js_entities($string);
    $string = wp_kses_normalize_entities($string);
    $string = wp_kses_hook($string, $allowed_html, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
    return wp_kses_split($string, $allowed_html, $allowed_protocols);
}

/**
 * Helper function to add global attributes to a tag in the allowed html list.
 *
 * @param array $value An array of attributes.
 * @return array The array of attributes with global attributes added.
 * @since 3.5.0
 * @access private
 *
 */
function _wp_add_global_attributes($value)
{
    $global_attributes = array(
        'class' => true,
        'id' => true,
        'style' => true,
        'title' => true,
        'role' => true,
    );

    if (true === $value)
        $value = array();

    if (is_array($value))
        return array_merge($value, $global_attributes);

    return $value;
}

function wp_allowed_protocols()
{
    static $protocols;

    if (empty($protocols)) {
        $protocols = array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp');

        $protocols = apply_filters('kses_allowed_protocols', $protocols);
    }

    return $protocols;
}

function wp_kses_no_null($string)
{
    $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string);
    $string = preg_replace('/(\\\\0)+/', '', $string);

    return $string;
}

/**
 * Removes the HTML JavaScript entities found in early versions of Netscape 4.
 *
 * @param string $string
 * @return string
 * @since 1.0.0
 *
 */
function wp_kses_js_entities($string)
{
    return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
}

/**
 * Converts and fixes HTML entities.
 *
 * This function normalizes HTML entities. It will convert "AT&T" to the correct
 * "AT&amp;T", "&#00058;" to "&#58;", "&#XYZZY;" to "&amp;#XYZZY;" and so on.
 *
 * @param string $string Content to normalize entities
 * @return string Content with normalized entities
 * @since 1.0.0
 *
 */
function wp_kses_normalize_entities($string)
{
    # Disarm all entities by converting & to &amp;

    $string = str_replace('&', '&amp;', $string);

    # Change back the allowed entities in our entity whitelist

    $string = preg_replace_callback('/&amp;([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $string);
    $string = preg_replace_callback('/&amp;#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string);
    $string = preg_replace_callback('/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string);

    return $string;
}

function wp_kses_hook($string, $allowed_html, $allowed_protocols)
{
    $string = apply_filters('pre_kses', $string, $allowed_html, $allowed_protocols);
    return $string;
}

function wp_kses_split($string, $allowed_html, $allowed_protocols)
{
    $GLOBALS['pass_allowed_html'] = $allowed_html;
    $GLOBALS['pass_allowed_protocols'] = $allowed_protocols;
    return preg_replace_callback('%(<!--.*?(-->|$))|(<[^>]*(>|$)|>)%', '_wp_kses_split_callback', $string);
}


function _wp_kses_split_callback($match)
{
    return wp_kses_split2($match[0], $GLOBALS['pass_allowed_html'], $GLOBALS['pass_allowed_protocols']);
}

function wp_kses_stripslashes($string)
{
    return preg_replace('%\\\\"%', '"', $string);
}

function wp_kses_allowed_html($context = '')
{
    if (is_array($context)) {
        return apply_filters('wp_kses_allowed_html', $context);
    }

    switch ($context) {
        case 'post':
            /** This filter is documented in wp-includes/kses.php */
            return apply_filters('wp_kses_allowed_html', wp_get_allowedposttags());
            break;
        case 'user_description':
        case 'pre_user_description':
            $tags = get_allowedtags();
            $tags['a']['rel'] = true;
            /** This filter is documented in wp-includes/kses.php */
            return apply_filters('wp_kses_allowed_html', $tags);
            break;
        case 'strip':
            /** This filter is documented in wp-includes/kses.php */
            return apply_filters('wp_kses_allowed_html', array());
            break;
        case 'entities':
            /** This filter is documented in wp-includes/kses.php */
            return apply_filters('wp_kses_allowed_html', get_allowedentitynames());
            break;
        case 'data':
        default:
            /** This filter is documented in wp-includes/kses.php */
            return apply_filters('wp_kses_allowed_html', get_allowedtags());
    }
}


function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols)
{
    # Is there a closing XHTML slash at the end of the attributes?

    if (!is_array($allowed_html))
        $allowed_html = wp_kses_allowed_html($allowed_html);

    $xhtml_slash = '';
    if (preg_match('%\s*/\s*$%', $attr))
        $xhtml_slash = ' /';

    # Are any attributes allowed at all for this element?
    if (!isset($allowed_html[strtolower($element)]) || count($allowed_html[strtolower($element)]) == 0)
        return "<$element$xhtml_slash>";

    # Split it
    $attrarr = wp_kses_hair($attr, $allowed_protocols);

    # Go through $attrarr, and save the allowed attributes for this element
    # in $attr2
    $attr2 = '';

    $allowed_attr = $allowed_html[strtolower($element)];
    foreach ($attrarr as $arreach) {
        if (!isset($allowed_attr[strtolower($arreach['name'])]))
            continue; # the attribute is not allowed

        $current = $allowed_attr[strtolower($arreach['name'])];
        if ($current == '')
            continue; # the attribute is not allowed

        if (strtolower($arreach['name']) == 'style') {
            $orig_value = $arreach['value'];
            $value = safecss_filter_attr($orig_value);

            if (empty($value))
                continue;

            $arreach['value'] = $value;
            $arreach['whole'] = str_replace($orig_value, $value, $arreach['whole']);
        }

        if (!is_array($current)) {
            $attr2 .= ' ' . $arreach['whole'];
            # there are no checks

        } else {
            # there are some checks
            $ok = true;
            foreach ($current as $currkey => $currval) {
                if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) {
                    $ok = false;
                    break;
                }
            }

            if ($ok)
                $attr2 .= ' ' . $arreach['whole']; # it passed them
        } # if !is_array($current)
    } # foreach

    # Remove any "<" or ">" characters
    $attr2 = preg_replace('/[<>]/', '', $attr2);

    return "<$element$attr2$xhtml_slash>";
}


function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue)
{
    $ok = true;

    switch (strtolower($checkname)) {
        case 'maxlen' :

            if (strlen($value) > $checkvalue)
                $ok = false;
            break;

        case 'minlen' :

            if (strlen($value) < $checkvalue)
                $ok = false;
            break;

        case 'maxval' :

            if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
                $ok = false;
            if ($value > $checkvalue)
                $ok = false;
            break;

        case 'minval' :

            if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
                $ok = false;
            if ($value < $checkvalue)
                $ok = false;
            break;

        case 'valueless' :

            if (strtolower($checkvalue) != $vless)
                $ok = false;
            break;
    } # switch

    return $ok;
}


function safecss_filter_attr($css, $deprecated = '')
{
    if (!empty($deprecated))
        _deprecated_argument(__FUNCTION__, '2.8.1');

    $css = wp_kses_no_null($css);
    $css = str_replace(array("\n", "\r", "\t"), '', $css);

    if (preg_match('%[\\\\(&=}]|/\*%', $css))
        return '';

    $css_array = explode(';', trim($css));

    $allowed_attr = apply_filters('safe_style_css', array('text-align', 'margin', 'color', 'float',
        'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color',
        'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
        'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color',
        'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top',
        'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'caption-side',
        'clear', 'cursor', 'direction', 'font', 'font-family', 'font-size', 'font-style',
        'font-variant', 'font-weight', 'height', 'letter-spacing', 'line-height', 'margin-bottom',
        'margin-left', 'margin-right', 'margin-top', 'overflow', 'padding', 'padding-bottom',
        'padding-left', 'padding-right', 'padding-top', 'text-decoration', 'text-indent', 'vertical-align',
        'width'));

    if (empty($allowed_attr))
        return $css;

    $css = '';
    foreach ($css_array as $css_item) {
        if ($css_item == '')
            continue;
        $css_item = trim($css_item);
        $found = false;
        if (strpos($css_item, ':') === false) {
            $found = true;
        } else {
            $parts = explode(':', $css_item);
            if (in_array(trim($parts[0]), $allowed_attr))
                $found = true;
        }
        if ($found) {
            if ($css != '')
                $css .= ';';
            $css .= $css_item;
        }
    }

    return $css;
}

function wp_kses_hair($attr, $allowed_protocols)
{
    $attrarr = array();
    $mode = 0;
    $attrname = '';
    $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action');

    while (strlen($attr) != 0) {
        $working = 0;

        switch ($mode) {
            case 0 :

                if (preg_match('/^([-a-zA-Z:]+)/', $attr, $match)) {
                    $attrname = $match[1];
                    $working = $mode = 1;
                    $attr = preg_replace('/^[-a-zA-Z:]+/', '', $attr);
                }

                break;

            case 1 :

                if (preg_match('/^\s*=\s*/', $attr)) {
                    $working = 1;
                    $mode = 2;
                    $attr = preg_replace('/^\s*=\s*/', '', $attr);
                    break;
                }

                if (preg_match('/^\s+/', $attr)) {
                    $working = 1;
                    $mode = 0;
                    if (false === array_key_exists($attrname, $attrarr)) {
                        $attrarr[$attrname] = array('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
                    }
                    $attr = preg_replace('/^\s+/', '', $attr);
                }

                break;

            case 2 :

                if (preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match)) # "value"
                {
                    $thisval = $match[1];
                    if (in_array(strtolower($attrname), $uris))
                        $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);

                    if (false === array_key_exists($attrname, $attrarr)) {
                        $attrarr[$attrname] = array('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
                    }
                    $working = 1;
                    $mode = 0;
                    $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
                    break;
                }

                if (preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match)) # 'value'
                {
                    $thisval = $match[1];
                    if (in_array(strtolower($attrname), $uris))
                        $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);

                    if (false === array_key_exists($attrname, $attrarr)) {
                        $attrarr[$attrname] = array('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
                    }
                    $working = 1;
                    $mode = 0;
                    $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
                    break;
                }

                if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) # value
                {
                    $thisval = $match[1];
                    if (in_array(strtolower($attrname), $uris))
                        $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);

                    if (false === array_key_exists($attrname, $attrarr)) {
                        $attrarr[$attrname] = array('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
                    }
                    # We add quotes to conform to W3C's HTML spec.
                    $working = 1;
                    $mode = 0;
                    $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
                }

                break;
        } # switch

        if ($working == 0) # not well formed, remove and try again
        {
            $attr = wp_kses_html_error($attr);
            $mode = 0;
        }
    } # while

    if ($mode == 1 && false === array_key_exists($attrname, $attrarr))
        $attrarr[$attrname] = array('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');

    return $attrarr;
}

function wp_kses_html_error($string)
{
    return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
}

function wp_kses_bad_protocol($string, $allowed_protocols)
{
    $string = wp_kses_no_null($string);
    $iterations = 0;

    do {
        $original_string = $string;
        $string = wp_kses_bad_protocol_once($string, $allowed_protocols);
    } while ($original_string != $string && ++$iterations < 6);

    if ($original_string != $string)
        return '';

    return $string;
}

function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1)
{
    $string2 = preg_split('/:|&#0*58;|&#x0*3a;/i', $string, 2);
    if (isset($string2[1]) && !preg_match('%/\?%', $string2[0])) {
        $string = trim($string2[1]);
        $protocol = wp_kses_bad_protocol_once2($string2[0], $allowed_protocols);
        if ('feed:' == $protocol) {
            if ($count > 2)
                return '';
            $string = wp_kses_bad_protocol_once($string, $allowed_protocols, ++$count);
            if (empty($string))
                return $string;
        }
        $string = $protocol . $string;
    }

    return $string;
}

function wp_kses_bad_protocol_once2($string, $allowed_protocols)
{
    $string2 = wp_kses_decode_entities($string);
    $string2 = preg_replace('/\s/', '', $string2);
    $string2 = wp_kses_no_null($string2);
    $string2 = strtolower($string2);

    $allowed = false;
    foreach ((array)$allowed_protocols as $one_protocol)
        if (strtolower($one_protocol) == $string2) {
            $allowed = true;
            break;
        }

    if ($allowed)
        return "$string2:";
    else
        return '';
}

function wp_kses_decode_entities($string)
{
    $string = preg_replace_callback('/&#([0-9]+);/', '_wp_kses_decode_entities_chr', $string);
    $string = preg_replace_callback('/&#[Xx]([0-9A-Fa-f]+);/', '_wp_kses_decode_entities_chr_hexdec', $string);

    return $string;
}

function _wp_kses_decode_entities_chr($match)
{
    return chr($match[1]);
}


function _wp_kses_decode_entities_chr_hexdec($match)
{
    return chr(hexdec($match[1]));
}

function wp_kses_split2($string, $allowed_html, $allowed_protocols)
{
    $string = wp_kses_stripslashes($string);

    if (substr($string, 0, 1) != '<')
        return '&gt;';

    if ('<!--' == substr($string, 0, 4)) {
        $string = str_replace(array('<!--', '-->'), '', $string);
        while ($string != ($newstring = kses($string, $allowed_html, $allowed_protocols)))
            $string = $newstring;
        if ($string == '')
            return '';
        $string = preg_replace('/--+/', '-', $string);
        $string = preg_replace('/-$/', '', $string);
        return "<!--{$string}-->";
    }

    if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
        return '';

    $slash = trim($matches[1]);
    $elem = $matches[2];
    $attrlist = $matches[3];

    if (!is_array($allowed_html))
        $allowed_html = wp_kses_allowed_html($allowed_html);

    if (!isset($allowed_html[strtolower($elem)]))
        return '';
    if ($slash != '')
        return "</$elem>";
    return wp_kses_attr($elem, $attrlist, $allowed_html, $allowed_protocols);
}

function wp_pre_kses_less_than($text)
{
    return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $text);
}

function wp_pre_kses_less_than_callback($matches)
{
    if (false === strpos($matches[0], '>'))
        return esc_html($matches[0]);
    return $matches[0];
}

function esc_html($text)
{
    $safe_text = wp_check_invalid_utf8($text);
    $safe_text = _wp_specialchars($safe_text, ENT_QUOTES);
    return apply_filters('esc_html', $safe_text, $text);
}

function wp_check_invalid_utf8($string, $strip = false)
{
    $string = (string)$string;

    if (0 === strlen($string)) {
        return '';
    }
    static $is_utf8;
    if (!isset($is_utf8)) {
        $is_utf8 = true;
    }
    if (!$is_utf8) {
        return $string;
    }
    static $utf8_pcre;
    if (!isset($utf8_pcre)) {
        $utf8_pcre = @preg_match('/^./u', 'a');
    }
    if (!$utf8_pcre) {
        return $string;
    }
    if (1 === @preg_match('/^./us', $string)) {
        return $string;
    }
    if ($strip && function_exists('iconv')) {
        return iconv('utf-8', 'utf-8', $string);
    }

    return '';
}

function _wp_specialchars($string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false)
{
    $string = (string)$string;

    if (0 === strlen($string))
        return '';
    if (!preg_match('/[&<>"\']/', $string))
        return $string;
    if (empty($quote_style))
        $quote_style = ENT_NOQUOTES;
    elseif (!in_array($quote_style, array(0, 2, 3, 'single', 'double'), true))
        $quote_style = ENT_QUOTES;
    if (!$charset) {
        static $_charset;
        if (!isset($_charset)) {
            $alloptions = array();
            $_charset = isset($alloptions['blog_charset']) ? $alloptions['blog_charset'] : '';
        }
        $charset = $_charset;
    }

    if (in_array($charset, array('utf8', 'utf-8', 'UTF8')))
        $charset = 'UTF-8';

    $_quote_style = $quote_style;

    if ($quote_style === 'double') {
        $quote_style = ENT_COMPAT;
        $_quote_style = ENT_COMPAT;
    } elseif ($quote_style === 'single') {
        $quote_style = ENT_NOQUOTES;
    }
    if ($double_encode) {
        $string = @htmlspecialchars($string, $quote_style, $charset);
    } else {
        $string = wp_specialchars_decode($string, $_quote_style);
        $string = wp_kses_normalize_entities($string);
        $string = preg_split('/(&#?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE);

        for ($i = 0; $i < count($string); $i += 2)
            $string[$i] = @htmlspecialchars($string[$i], $quote_style, $charset);

        $string = implode('', $string);
    }
    if ('single' === $_quote_style)
        $string = str_replace("'", '&#039;', $string);

    return $string;
}

function wp_specialchars_decode($string, $quote_style = ENT_NOQUOTES)
{
    $string = (string)$string;

    if (0 === strlen($string)) {
        return '';
    }
    if (strpos($string, '&') === false) {
        return $string;
    }
    if (empty($quote_style)) {
        $quote_style = ENT_NOQUOTES;
    } elseif (!in_array($quote_style, array(0, 2, 3, 'single', 'double'), true)) {
        $quote_style = ENT_QUOTES;
    }
    $single = array('&#039;' => '\'', '&#x27;' => '\'');
    $single_preg = array('/&#0*39;/' => '&#039;', '/&#x0*27;/i' => '&#x27;');
    $double = array('&quot;' => '"', '&#034;' => '"', '&#x22;' => '"');
    $double_preg = array('/&#0*34;/' => '&#034;', '/&#x0*22;/i' => '&#x22;');
    $others = array('&lt;' => '<', '&#060;' => '<', '&gt;' => '>', '&#062;' => '>', '&amp;' => '&', '&#038;' => '&', '&#x26;' => '&');
    $others_preg = array('/&#0*60;/' => '&#060;', '/&#0*62;/' => '&#062;', '/&#0*38;/' => '&#038;', '/&#x0*26;/i' => '&#x26;');

    if ($quote_style === ENT_QUOTES) {
        $translation = array_merge($single, $double, $others);
        $translation_preg = array_merge($single_preg, $double_preg, $others_preg);
    } elseif ($quote_style === ENT_COMPAT || $quote_style === 'double') {
        $translation = array_merge($double, $others);
        $translation_preg = array_merge($double_preg, $others_preg);
    } elseif ($quote_style === 'single') {
        $translation = array_merge($single, $others);
        $translation_preg = array_merge($single_preg, $others_preg);
    } elseif ($quote_style === ENT_NOQUOTES) {
        $translation = $others;
        $translation_preg = $others_preg;
    }
    $string = preg_replace(array_keys($translation_preg), array_values($translation_preg), $string);
    return strtr($string, $translation);
}

function wp_kses_named_entities($matches)
{

    if (empty($matches[1]))
        return '';

    $i = $matches[1];
    return ((!in_array($i, get_allowedentitynames())) ? "&amp;$i;" : "&$i;");
}

function wp_kses_normalize_entities2($matches)
{
    if (empty($matches[1]))
        return '';

    $i = $matches[1];
    if (valid_unicode($i)) {
        $i = str_pad(ltrim($i, '0'), 3, '0', STR_PAD_LEFT);
        $i = "&#$i;";
    } else {
        $i = "&amp;#$i;";
    }

    return $i;
}

function wp_kses_normalize_entities3($matches)
{
    if (empty($matches[1]))
        return '';

    $hexchars = $matches[1];
    return ((!valid_unicode(hexdec($hexchars))) ? "&amp;#x$hexchars;" : '&#x' . ltrim($hexchars, '0') . ';');
}

function valid_unicode($i)
{
    return ($i == 0x9 || $i == 0xa || $i == 0xd ||
        ($i >= 0x20 && $i <= 0xd7ff) ||
        ($i >= 0xe000 && $i <= 0xfffd) ||
        ($i >= 0x10000 && $i <= 0x10ffff));
}

function wp_kses_post($data)
{
    return wp_kses($data, 'post');
}

function esc_attr($text)
{
    $safe_text = wp_check_invalid_utf8($text);
    $safe_text = _wp_specialchars($safe_text, ENT_QUOTES);
    return apply_filters('attribute_escape', $safe_text, $text);
}

function wp_strip_all_tags($string, $remove_breaks = false)
{
    $string = preg_replace('@<(script|style)[^>]*?>.*?</\\1>@si', '', $string);
    $string = strip_tags($string);

    if ($remove_breaks)
        $string = preg_replace('/[\r\n\t ]+/', ' ', $string);

    return trim($string);
}